/*
 * @(#)JwiWordNet.java	1.0 09/01/07
 *
 * Copyright 2007 Fabio Gasparetti. All rights reserved.
 */

package org.tabularium.text.nlp.wordnet.jwi;

import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import java.util.prefs.Preferences;

import org.tabularium.text.nlp.JwiStemmer;
import org.tabularium.text.nlp.Stemmer;
import org.tabularium.text.nlp.wordnet.Relationship;
import org.tabularium.text.nlp.wordnet.Synset;
import org.tabularium.text.nlp.wordnet.WordNet;
import org.tabularium.text.nlp.wordnet.WordSense;

import edu.mit.jwi.dict.IDictionary;
import edu.mit.jwi.item.IIndexWord;
import edu.mit.jwi.item.ISynset;
import edu.mit.jwi.item.ISynsetID;
import edu.mit.jwi.item.IWord;
import edu.mit.jwi.item.IWordID;
import edu.mit.jwi.morph.SimpleStemmer;

/**
 * Implementation of WordNet based on MIT Java Wordnet Interface (JWI).
 * <p>
 * A typical invocation sequence is:
 * <blockquote><pre>
 * JwiWordNet wn = new JwiWordNet();
 * wn.init("/home/fabio/projects/WordNet-3.0/dict");
 * Synset[] ss = wn.getSynsets("house", PartOfSpeech.VERB);
 * </pre></blockquot>
 * See {@link http://www.mit.edu/~markaf/projects/wordnet/}
 * 
 * @author Fabio Gasparetti
 * @version 1.0, 09/01/07
 */
public class JwiWordNet extends IndexSenseWordNet implements WordNet {
	protected Stemmer stemmer = null;

	public JwiWordNet() {

	}

	public JwiWordNet(Stemmer stemmer) {
		this.stemmer = stemmer;
	}

	/**
	 * Init with wordnet directory retrieved from preference wordnet.home in
	 * node 'org/tabularium/cues-extractor' and with stemming based on
	 * JwiStemmer.
	 */
	
//	public void init() throws Exception {
//		super.init();
//		Preferences prefs = Preferences.userRoot().node(
//				"org/tabularium/cues-extractor");
//		String path = prefs.get("wordnet.home",
//				"/home/fabio/projects/cues/WordNet-3.0/dict");
//		super.init(path);
//	}


	public org.tabularium.text.nlp.wordnet.Synset[] getRelatedSynsets(
			org.tabularium.text.nlp.wordnet.Synset s) {
		ArrayList synsets = new ArrayList();
		// translate tabularium POS -> jwi POS
		JwiSynset s1 = (JwiSynset) s;
		ISynset s2 = dict.getSynset(s1.jwiSynsetID);
		ISynsetID[] relatedSyns = s2.getRelatedSynsets();
		for (int i = 0; i < relatedSyns.length; i++) {
			ISynsetID sid = relatedSyns[i];
			ISynset s3 = dict.getSynset(sid);
			JwiSynset synset = new JwiSynset();
			synset.pos = JwiPartOfSpeech.translate(s3.getPartOfSpeech());
			synset.jwiSynsetID = sid;
			synset.gloss = s3.getGloss();
			synsets.add(synset);
		}
		return (org.tabularium.text.nlp.wordnet.Synset[]) synsets
				.toArray(new org.tabularium.text.nlp.wordnet.Synset[] {});
	}

	public org.tabularium.text.nlp.wordnet.Synset[] getRelatedSynsets(
			org.tabularium.text.nlp.wordnet.Synset s, int relationshipType) {
		ArrayList synsets = new ArrayList();
		// translate tabularium POS -> jwi POS
		JwiSynset s1 = (JwiSynset) s;
		ISynset s2 = dict.getSynset(s1.jwiSynsetID);
		ISynsetID[] relatedSyns = s2.getRelatedSynsets(JwiRelationship
				.translate(relationshipType));
		for (int i = 0; i < relatedSyns.length; i++) {
			ISynsetID sid = relatedSyns[i];
			ISynset s3 = dict.getSynset(sid);
			JwiSynset synset = new JwiSynset();
			synset.pos = JwiPartOfSpeech.translate(s3.getPartOfSpeech());
			synset.jwiSynsetID = sid;
			synset.gloss = s3.getGloss();
			synsets.add(synset);
		}
		return (org.tabularium.text.nlp.wordnet.Synset[]) synsets
				.toArray(new org.tabularium.text.nlp.wordnet.Synset[] {});
	}

	public WordSense[] getWordSenses(org.tabularium.text.nlp.wordnet.Synset s) {
		ArrayList wordSenses = new ArrayList();
		// translate tabularium POS -> jwi POS
		JwiSynset s1 = (JwiSynset) s;
		ISynset s2 = dict.getSynset(s1.jwiSynsetID);
		IWord[] synWords = s2.getWords();
		for (int i = 0; i < synWords.length; i++) {
			String lemma = synWords[i].getLemma();
			lemma = lemma.replace('_', ' ');
			JwiWordSense wordSense = new JwiWordSense();
			wordSense.lemma = lemma;
			wordSense.jwiSynsetID = s1.jwiSynsetID;
			wordSense.pos = JwiPartOfSpeech.translate(s1.jwiSynsetID
					.getPartOfSpeech());
			wordSenses.add(wordSense);
		}
		return (org.tabularium.text.nlp.wordnet.WordSense[]) wordSenses
				.toArray(new org.tabularium.text.nlp.wordnet.WordSense[] {});
	}

	public org.tabularium.text.nlp.wordnet.Synset getSynset(WordSense sense) {
		JwiWordSense s1 = (JwiWordSense) sense;
		ISynset s2 = dict.getSynset(s1.jwiSynsetID);
		JwiSynset synset = new JwiSynset();
		synset.pos = JwiPartOfSpeech.translate(s2.getPartOfSpeech());
		synset.jwiSynsetID = s1.jwiSynsetID;
		synset.gloss = s2.getGloss();
		return synset;
	}

	public org.tabularium.text.nlp.wordnet.Synset[] getSynsets(String word, int pos) {
		// translate tabularium POS -> jwi POS
		edu.mit.jwi.item.PartOfSpeech jwiPos = JwiPartOfSpeech.translate(pos);

		TreeSet queryingWords = new TreeSet();
		String underscored = word.replace(' ', '_');
		queryingWords.add(underscored);
		if (stemmer != null) {
			Set stems = stemmer.getRoots(word, pos);
			if (stems != null)
				queryingWords.addAll(stems);
		}		
		ArrayList synsets = new ArrayList();
		Iterator wordIter = queryingWords.iterator();
		while (wordIter.hasNext()) {
			String word1 = (String) wordIter.next();
			// Returns ids of all words (index word+synset pairs) assocated with
			// this index word.
			IIndexWord idxWord = dict.getIndexWord(word1, jwiPos);
			if (idxWord == null)
				continue;

			IWordID[] wordIDs = idxWord.getWordIDs();
			for (int i = 0; i < wordIDs.length; i++) {
				// Represents a unique identifier sufficient to retrieve a
				// particular IWord object from the Wordnet database.
				IWordID wordID = idxWord.getWordIDs()[i];
				// Fetches the word from the database, as specified by the
				// indicated
				// IWordID object.
				IWord w = dict.getWord(wordID);
				ISynsetID sid = wordID.getSynsetID();
				ISynset s = dict.getSynset(sid);
				JwiSynset synset = new JwiSynset();
				synset.pos = pos;
				synset.jwiSynsetID = sid;
				synset.gloss = s.getGloss();
				synsets.add(synset);
			}
		}
		return (org.tabularium.text.nlp.wordnet.Synset[]) synsets
				.toArray(new org.tabularium.text.nlp.wordnet.Synset[] {});
	}

	public String[] getWords(org.tabularium.text.nlp.wordnet.Synset s) {
		ArrayList words = new ArrayList();
		JwiSynset s1 = (JwiSynset) s;
		ISynset synset = dict.getSynset(s1.jwiSynsetID);
		IWord[] synWords = synset.getWords();
		for (int i = 0; i < synWords.length; i++) {
			String lemma = synWords[i].getLemma();
			lemma = lemma.replace('_', ' ');
			words.add(lemma);
		}
		return (String[]) words.toArray(new String[] {});
	}

	public static void main(String args[]) throws Exception {
		try {
			JwiWordNet wn = new JwiWordNet();
			wn.init();
			org.tabularium.text.nlp.wordnet.Synset[] ss = wn.getSynsets("house",
					org.tabularium.text.nlp.wordnet.PartOfSpeech.VERB);
			for (int i = 0; i < ss.length; i++) {
				int freq = wn.getSynsetFreq(ss[i]);
				System.out.println("freq: " + freq);
				System.out.println("xsynset (" + (i + 1) + "): "
						+ ss[i].toString());
				String[] ww = wn.getWords(ss[i]);
				for (int j = 0; j < ww.length; j++) {
					System.out.println("\t xword (" + (j + 1) + "): " + ww[j]);
				}
				WordSense[] wss = wn.getWordSenses(ss[i]);
				for (int j = 0; j < wss.length; j++) {
					System.out.println("\t xwordsenes (" + (j + 1) + "): "
							+ wss[j].toString());
					System.out.println("\t\t xsynset (" + (j + 1) + "): "
							+ wn.getSynset(wss[j]).toString());
				}
				org.tabularium.text.nlp.wordnet.Synset[] ss2 = wn.getRelatedSynsets(
						ss[i], Relationship.ENTAILMENT);
				for (int j = 0; j < ss2.length; j++) {
					System.out.println("\t xrelated-synsets ENTAILMENT ("
							+ (j + 1) + "): " + ss2[j].toString());
				}
				org.tabularium.text.nlp.wordnet.Synset[] ss3 = wn.getRelatedSynsets(
						ss[i], Relationship.HYPONYM);
				for (int j = 0; j < ss3.length; j++) {
					System.out.println("\t xrelated-synsets HYPONYM ("
							+ (j + 1) + "): " + ss3[j].toString());
				}
				System.out.println();
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public Iterator synsets(int pos) {
		return new JwiIterator(dict.getSynsetIterator(JwiPartOfSpeech.translate(pos)));
	}

}
